package com.liujianlei.forum_system.service.impl;

import com.liujianlei.forum_system.common.AppResult;
import com.liujianlei.forum_system.common.ResultCode;
import com.liujianlei.forum_system.dao.ArticleMapper;
import com.liujianlei.forum_system.dao.BoardMapper;
import com.liujianlei.forum_system.dao.UserMapper;
import com.liujianlei.forum_system.exception.ApplicationException;
import com.liujianlei.forum_system.model.Article;
import com.liujianlei.forum_system.service.IArticleService;
import com.liujianlei.forum_system.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * @author tongchen
 * @create 2023-06-11 20:14
 */
@Service
@Slf4j
public class IArticleServiceImpl implements IArticleService {
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private BoardMapper boardMapper;
    private String redisArticleBoard="articleBoard_";
    private String redisArticleUser="articleUser_";
    @Resource
    private UserMapper userMapper;
    @Resource
    private ArticleMapper articleMapper;
    @Override
    public List<Article> selectAll() {
        //查看redis中是否存在文章，如果存在直接调用并返回，不存在则调用mapper添加后返回
        List<Article> list = (List<Article>) redisTemplate.opsForValue().get(redisArticleBoard);
        if(list!=null&&list.size()>0){
            log.info("通过缓存直接返回");
            return list;
        }else{
            log.info("通过数据库查询....");
            //直接调用mapper
            List<Article> articles = articleMapper.selectAll();
            //存入缓存
            redisTemplate.opsForValue().set(redisArticleBoard, articles);
            return articles;
        }

    }

    @Override
    public List<Article> selectByBoardId(Long id) {
        //参数校验
        if(id<=0){
            throw new ApplicationException(ResultCode.FAILED_PARAMS_VALIDATE.toString());
        }
        //进行redis缓存
        String redisBoard=redisArticleBoard+id;
        List<Article> articles = setRedisCache(redisBoard, id);
        return articles;

    }

    @Override
    public List<Article> selectByUserId(Long id) {
        //判断id的有效性
        if(id<=0){
            //抛出异常
            throw new ApplicationException(ResultCode.FAILED_PARAMS_VALIDATE.toString());
        }
        String redisUser=redisArticleUser+id;
        List<Article> list= (List<Article>) redisTemplate.opsForValue().get(redisUser);
        if(list==null||list.size()==0){
            //直接调用mapper
            List<Article> articles = articleMapper.selectByUserId(id);
            //存入缓存
            redisTemplate.opsForValue().set(redisUser, articles);
            return articles;
        }else{
            log.info("通过缓存直接返回");
            return list;
        }

    }

    @Override
    @Transactional
    public void insertArticle(Article article) {
        //检验参数的有效性
        if(article==null||article.getUserId()==null||article.getBoardId()==null){
            //记录错误信息
            log.error("填充的信息不完整");
            throw new ApplicationException(ResultCode.FAILED_PARAMS_VALIDATE.toString());
        }
        //填充默认数据
        article.setVisitCount(0); // 访问数量
        article.setReplyCount(0); // 回复数量
        article.setLikeCount(0); // 点赞数量
        article.setState((byte) 0); // 状态
        article.setDeleteState((byte) 0); // 是否删除
        Date date = new Date();
        article.setCreateTime(date);
        article.setUpdateTime(date);
        //在数据库中插入数据
        deleteCache(article);
        int result = articleMapper.insertSelective(article);
        if(result!=1){
            //记录错误信息
            log.error(ResultCode.FAILED_CREATE.toString());
            throw new ApplicationException(ResultCode.FAILED_CREATE.toString());
        }
        //更新总表数据个人数据和分类数据


        //更新其他表中的数据
        int resultBoard = boardMapper.updateArticleCountById(article.getBoardId());
        int resultUser = userMapper.updateArticleCountById(article.getUserId());
        if(resultBoard!=1){
            //记录错误信息
            log.error(ResultCode.FAILED_CREATE.toString()+"resultBoard"+resultBoard);
            throw new ApplicationException(ResultCode.FAILED_CREATE.toString());
        }
        if(resultUser!=1){
            log.error(ResultCode.FAILED_CREATE.toString()+"resultUser"+resultUser);
            throw new ApplicationException(ResultCode.FAILED_CREATE.toString());
        }
        //记录插入成功信息
        log.info("文章新增成功"+"userid:"+article.getUserId()+"boardId"+article.getBoardId());
    }

    @Override
    public Article selectDetailById(Long id) {
        //判断id有效性
        if(id==null){
            //记录错误信息并报错
            log.error(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //查询数据
        Article article = articleMapper.selectDetailById(id);
        log.info("帖子具体内容信息为："+article);
        //数据为空直接报错
        if(article==null){
            log.error(ResultCode.FAILED_NOT_EXISTS.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_NOT_EXISTS));
        }
        //数据不为空设置修改的article数据
        //创建要修改的article
        Article update = new Article();
        update.setId(article.getId());
        update.setLikeCount(article.getLikeCount()+1);
        //将修改数据返回
        int result = articleMapper.updateByPrimaryKeySelective(update);
        if(result!=1){
            log.error(ResultCode.ERROR_UPDATE.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_UPDATE));
        }
        //最后修改查询数据并返回
        article.setVisitCount(article.getVisitCount()+1);
        return article;
    }

    @Override
    public void modify(String title, String content, Long id) {
        //查看参数的有效性
        if(id==null||StringUtils.isEmpty(content)){
            //抛出异常
            log.error(ResultCode.ERROR_IS_NULL.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_IS_NULL));
        }
        //查询数据
        Article article = articleMapper.selectByPrimaryKey(id);

        //设置修改对象
        Article update = new Article();
        update.setContent(content);
        update.setId(id);
        update.setUpdateTime(new Date());
        //查询修改结果

        int result = articleMapper.updateByPrimaryKeySelective(update);
        if(result!=1){
            log.error(ResultCode.ERROR_UPDATE.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_UPDATE));
        }
        deleteCache(article);
        log.info("数据更新成功，更新条数"+result);
    }

    @Override
    public void thumbsUpById(Long id) {
        //根据文章id对文章进行点赞操作
        if(id==null){
        log.error("文章id为空");
        throw new ApplicationException(AppResult.failed(ResultCode.ERROR_IS_NULL));
        }
        Article article = selectDetailById(id);
        //对文章的状态进行判断
        if(article==null||article.getState()==1||article.getDeleteState()==1){
            log.error("文章状态错误,articleState="+article.getState()+"文章删除信息错误"+article.getDeleteState());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //创建用户并进行点赞
        Article update = new Article();
        update.setId(id);
        update.setLikeCount((article.getLikeCount())+1);
        int result = articleMapper.updateByPrimaryKeySelective(update);
        if(result!=1){
            //记录错误信息并抛出异常
            log.error("数据更新异常");
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_UPDATE));
        }
            log.info("点赞成功");
    }

    @Override
    public void deleteArticle(Long id) {
        //查看id的有效性
        if(id==null){
            log.error("id信息不能为空");
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_IS_NULL));
        }
        //根据id查询文章信息
        Article article = articleMapper.selectDetailById(id);
        log.info("帖子信息为"+article);
        //信息不符合要求直接报错
        if(article==null||article.getDeleteState()==1||article.getState()==1){
            //写日志并报错
            log.error("帖子信息不符合要求");
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));

        }
        //设置更新后的文章
        Article update = new Article();
        update.setId(id);
        update.setDeleteState((byte) 1);
        deleteCache(article);
        //调用mapper修改文章
        articleMapper.updateByPrimaryKeySelective(update);
    }
    public List<Article> setRedisCache(String cacheName, Long id){;
        //进行查询
        List<Article> list= (List<Article>) redisTemplate.opsForValue().get(cacheName);
        if(list==null||list.size()==0){
            //直接调用mapper
            List<Article> articles = articleMapper.selectByBoardId(id);
            //存入缓存
            redisTemplate.opsForValue().set(cacheName, articles);
            return articles;
        }else{
            log.info("通过缓存直接返回");
            return list;
        }
    }
    public void deleteCache(Article article){
        Set keyAll = redisTemplate.keys(redisArticleBoard);
        Set keyBoard = redisTemplate.keys(redisArticleBoard + article.getBoardId());
        Set keyUser = redisTemplate.keys(redisArticleUser + article.getUserId());
        redisTemplate.delete(keyAll);
        redisTemplate.delete(keyBoard);
        redisTemplate.delete(keyUser);
    }
}
